package com.stary.code;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.velocity.Template;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.stary.code.exception.GenerateErrorException;
import com.stary.code.springboot.config.LogBackConfig;
import com.stary.code.springboot.config.MailConfig;
import com.stary.code.springboot.config.MavenConfig;
import com.stary.code.springboot.config.MybatisPlusConfig;
import com.stary.code.springboot.config.SpringBootProjectConfig;
import com.stary.code.springboot.config.TablesDocConfig;
import com.stary.code.springboot.config.TemplateConfig;
import com.stary.code.springboot.config.data.DataSourceConfig;
import com.stary.code.springboot.config.data.MongoDBConfig;
import com.stary.code.springboot.config.data.RedisConfig;
import com.stary.code.springboot.config.mq.ActiveMQConfig;
import com.stary.code.springboot.config.mq.KafkaConfig;
import com.stary.code.springboot.config.mq.RabbitMQConfig;
import com.stary.code.springboot.config.search.ElasticSearchConfig;
import com.stary.code.springboot.config.search.SolrConfig;
import com.stary.code.springboot.rules.Constants;
import com.stary.code.springboot.rules.DataSourcePoolType;
import com.stary.code.springboot.rules.SimpleDependency;
import com.stary.code.springboot.rules.WebViewType;
import com.stary.code.util.JDBCUtils;
import com.stary.code.util.SqlFileExecutor;
import com.stary.mybatisplus.generator.config.DbDriverName;

/**
 * 自动生成springboot项目
 * @author stary
 * @date 2018年6月29日 上午9:56:35
 */
public class AutoGenerator {

	private static final Logger logger=LoggerFactory.getLogger(AutoGenerator.class);

	private final String WAR="war";
	/**
	 * 项目生成根目录
	 */
	private  String outDir="e:/";
	/**
	 * 开发人员
	 */
	private String author="stary";

	/**
	 * 数据源配置
	 */
	private DataSourceConfig dataSourceConfig;
	/**
	 * maven配置
	 */
	private MavenConfig mavenConfig;
	/**
	 * spring boot配置
	 */
	private SpringBootProjectConfig springBootProjectConfig;
	/**
	 * logback配置
	 */
	private LogBackConfig logBackConfig;
	/**
	 * MyBatisPlus代码生成器配置
	 */
	private MybatisPlusConfig mybatisPlusConfig;


	/**
	 * redis配置
	 */
	private RedisConfig redisConfig;
	/**
	 * mongoDB 配置
	 */
	private MongoDBConfig mongoDBConfig;
	/**
	 * 邮件配置
	 */
	private MailConfig mailConfig;

	/**
	 * activeMQ配置
	 */
	private ActiveMQConfig activeMQConfig;
	/**
	 * kafka配置
	 */
	private KafkaConfig kafkaConfig;
	/**
	 * rabbitMQ配置
	 */
	private RabbitMQConfig rabbitMQConfig;


	/**
	 * 表文档配置
	 */
	private TablesDocConfig tablesDocConfig;
	/**
	 * solr配置
	 */
	private SolrConfig solrConfig;
	/**
	 * elasticSearch配置
	 */
	private ElasticSearchConfig elasticSearchConfig;


	public ElasticSearchConfig getElasticSearchConfig() {
		return elasticSearchConfig;
	}


	public AutoGenerator setElasticSearchConfig(ElasticSearchConfig elasticSearchConfig) {
		this.elasticSearchConfig = elasticSearchConfig;
		return this;
	}


	public SolrConfig getSolrConfig() {
		return solrConfig;
	}


	public AutoGenerator setSolrConfig(SolrConfig solrConfig) {
		this.solrConfig = solrConfig;
		return this;

	}





	public TablesDocConfig getTablesDocConfig() {
		return tablesDocConfig;
	}


	public AutoGenerator setTablesDocConfig(TablesDocConfig tablesDocConfig) {
		this.tablesDocConfig = tablesDocConfig;
		return this;
	}


	public RabbitMQConfig getRabbitMQConfig() {
		return rabbitMQConfig;
	}


	public AutoGenerator setRabbitMQConfig(RabbitMQConfig rabbitMQConfig) {
		this.rabbitMQConfig = rabbitMQConfig;
		return this;
	}


	public KafkaConfig getKafkaConfig() {
		return kafkaConfig;
	}


	public AutoGenerator setKafkaConfig(KafkaConfig kafkaConfig) {
		this.kafkaConfig = kafkaConfig;
		return this;
	}


	public ActiveMQConfig getActiveMQConfig() {
		return activeMQConfig;
	}


	public AutoGenerator setActiveMQConfig(ActiveMQConfig activeMQConfig) {
		this.activeMQConfig = activeMQConfig;
		return this;
	}


	public MailConfig getMailConfig() {
		return mailConfig;
	}


	public AutoGenerator setMailConfig(MailConfig mailConfig) {
		this.mailConfig = mailConfig;
		return this;
	}


	public MongoDBConfig getMongoDBConfig() {
		return mongoDBConfig;
	}


	public AutoGenerator setMongoDBConfig(MongoDBConfig mongoDBConfig) {
		this.mongoDBConfig = mongoDBConfig;
		return this;
	}


	public String getAuthor() {
		return author;
	}


	public void setAuthor(String author) {
		this.author = author;
	}


	public MavenConfig getMavenConfig() {
		if(mavenConfig==null){			
			mavenConfig=new MavenConfig();
		}
		return mavenConfig;
	}
	public AutoGenerator setMavenConfig(MavenConfig mavenConfig) {
		this.mavenConfig = mavenConfig;
		return this;
	}
	public String getOutDir() {
		return outDir;
	}
	public void setOutDir(String outDir) {
		this.outDir = outDir;
	}


	public DataSourceConfig getDataSourceConfig() {
		return dataSourceConfig;
	}


	public AutoGenerator setDataSourceConfig(DataSourceConfig dataSourceConfig) {
		this.dataSourceConfig = dataSourceConfig;
		return this;
	}


	public LogBackConfig getLogBackConfig() {
		if(mavenConfig==null){
			throw new  GenerateErrorException("maven config is null");
		}
		logBackConfig.setFileName(mavenConfig.getArtifactId());
		return logBackConfig;

	}


	public AutoGenerator setLogBackConfig(LogBackConfig logBackConfig) {		
		this.logBackConfig = logBackConfig;
		return this;
	}

	public MybatisPlusConfig getMybatisPlusConfig() {				
		return mybatisPlusConfig;
	}
	public AutoGenerator setSpringBootProjectConfig(
			SpringBootProjectConfig springBootProjectConfig) {
		this.springBootProjectConfig = springBootProjectConfig;
		return this;
	}
	public SpringBootProjectConfig getSpringBootProjectConfig() {
		return springBootProjectConfig;
	}

	public AutoGenerator setMybatisPlusConfig(MybatisPlusConfig mybatisPlusConfig) {
		if(dataSourceConfig==null){
			throw new GenerateErrorException("data source is null");
		}
		mybatisPlusConfig.setDbUrl(dataSourceConfig.getUrl());
		mybatisPlusConfig.setDbUserName(dataSourceConfig.getUsername());
		mybatisPlusConfig.setDbPassword(dataSourceConfig.getPassword());
		if(dataSourceConfig.getType().equals(DbDriverName.ORACLE.getDb())){
			mybatisPlusConfig.setDbType(DbType.ORACLE);				
		}else if(dataSourceConfig.getType().equals(DbDriverName.MYSQL.getDb())){
			mybatisPlusConfig.setDbType(DbType.MYSQL);	
		}else if(dataSourceConfig.getType().equals(DbDriverName.SQLSERVER.getDb())){
			mybatisPlusConfig.setDbType(DbType.SQL_SERVER);	
		}
		mybatisPlusConfig.setOutputDir(outDir+mavenConfig.getMyBatisDir());
		mybatisPlusConfig.setPackageName(mavenConfig.getGroupId()+"." + mavenConfig.getArtifactId());	
		mybatisPlusConfig.setAuthor(getAuthor());
		this.mybatisPlusConfig = mybatisPlusConfig;
		return this;
	}
	
	public RedisConfig getRedisConfig() {
		return redisConfig;
	}

	public AutoGenerator setRedisConfig(RedisConfig redisConfig) {
		this.redisConfig = redisConfig;
		return this;
	}


	/**
	 * 初始化模板配置
	 * @return
	 */
	public TemplateConfig initTemplateConfig(){
		TemplateConfig templateConfig=new TemplateConfig();
		logger.debug("---------->> 初始化项目模板参数 <<----------");
		Map<String, Object> paramsMap=new HashMap<String, Object>(16);
		paramsMap.put("author",getAuthor());		
		paramsMap.put("mvncfg", getMavenConfig());
		paramsMap.put("sbcfg", getSpringBootProjectConfig());
		paramsMap.put("dscfg", getDataSourceConfig());		
		paramsMap.put("lbcfg", getLogBackConfig());		
		paramsMap.put("rcfg",getRedisConfig());
		paramsMap.put("mdcfg",getMongoDBConfig());
		paramsMap.put("mailcfg",getMailConfig());
		paramsMap.put("activemqcfg",getActiveMQConfig());
		paramsMap.put("rabbitmqcfg",getRabbitMQConfig());
		paramsMap.put("kafkacfg",getKafkaConfig());
		paramsMap.put("solrcfg",getSolrConfig());
		paramsMap.put("escfg",getElasticSearchConfig());
		paramsMap.put("date",new SimpleDateFormat("yyyy-MM-dd").format(new Date()));		
		paramsMap.put("app",templateConfig.upperCase(getMavenConfig().getArtifactId()) + Constants.APPLICATION);		
		paramsMap.put("sbapp",templateConfig.upperCase(getMavenConfig().getArtifactId()) + Constants.SPRING_BOOT_APPLICATION);		
		if(getSpringBootProjectConfig().isOpenDataSource()){
			if(getSpringBootProjectConfig().isTableDocCreated()){
				if(getDataSourceConfig()!=null){
					com.baomidou.mybatisplus.generator.config.DataSourceConfig dataSourceConfig=new com.baomidou.mybatisplus.generator.config.DataSourceConfig();
					dataSourceConfig.setDriverName(getDataSourceConfig().getDriverClassName());
					dataSourceConfig.setUrl(getDataSourceConfig().getUrl());
					dataSourceConfig.setUsername(getDataSourceConfig().getUsername());
					dataSourceConfig.setPassword(getDataSourceConfig().getPassword());
					StrategyConfig strategyConfig=new StrategyConfig();
					if(tablesDocConfig==null){
						tablesDocConfig=new TablesDocConfig();
						tablesDocConfig.setDocName(getMavenConfig().getName());
					}
					Set<TableInfo> newList=new HashSet<>();
					if(springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.MYBATIS_PLUS.getName())){
						String[] tables=getMybatisPlusConfig().getTables();
						strategyConfig.setInclude(tables);
					}
					// mybatis-plus工具
					ConfigBuilder builder=new ConfigBuilder(null, dataSourceConfig, strategyConfig, null, null);
					List<TableInfo> tList=builder.getTableInfoList();
					if(tablesDocConfig.getTablePrefixs()!=null){
						String[] tablePrefixs=tablesDocConfig.getTablePrefixs();
						for (TableInfo table : tList) {
							for (int i = 0; i < tablePrefixs.length; i++) {
								String tablePrefix = tablePrefixs[i];
								if(table.getName().startsWith(tablePrefix.toLowerCase()) || table.getName().startsWith(tablePrefix.toUpperCase())){
									newList.add(table);
								}									
							}
						}
					}else{
						for (TableInfo table : tList) {
							newList.add(table);
						}
					}
					if(StringUtils.isEmpty(tablesDocConfig.getDocName())){
						tablesDocConfig.setDocName(getMavenConfig().getName());
					}
					tablesDocConfig.setTables(newList);

				}
				paramsMap.put("tablesdoccfg",getTablesDocConfig());
			}

		}
		templateConfig.setParamsMap(paramsMap);	
		logger.debug("---------->> 初始化项目模板文件 <<----------");
		// 设置模板文件		
		Map<String, String> templatesMap=new HashMap<String, String>(16);
		templatesMap.put(Constants.POM, Constants.TEMPLATE_POM);
		templatesMap.put(Constants.APPLICATION, Constants.TEMPLATE_APPLICATION);

		if(WAR.equals(mavenConfig.getPackaging())){
			templatesMap.put(Constants.SPRING_BOOT_APPLICATION, Constants.TEMPLATE_SPRING_BOOT_APPLICATION);
		}
		templatesMap.put(Constants.APPLICATION_PRO_DEV, Constants.TEMPLATE_APPLICATION_PRO_DEV);
		templatesMap.put(Constants.APPLICATION_PRO_PROD, Constants.TEMPLATE_APPLICATION_PRO_PROD);
		templatesMap.put(Constants.APPLICATION_PRO, Constants.TEMPLATE_APPLICATION_PRO);
		templatesMap.put(Constants.TEST, mavenConfig.MAVEN_TEST_JAVA);
		if(springBootProjectConfig.isOpenView()){
			if(!springBootProjectConfig.getViewType().equals(WebViewType.JSP.getName())){
				templatesMap.put(Constants.TEMPLATES, Constants.TEMPLATES);
			}else{
				templatesMap.put(Constants.JSP, Constants.TEMPLATE_JSP);
			}
			templatesMap.put(Constants.STATIC, Constants.STATIC);
		}

		if(springBootProjectConfig.isOpenDataSource()){
			if(dataSourceConfig==null){
				throw new GenerateErrorException("data source is null");
			}
			// druid 使用druid-spring-boot-starter，不需要自己配置
			if(DataSourcePoolType.DRUID.getName().equals(dataSourceConfig.getPoolType())){
				springBootProjectConfig.getDependencyMap().put(SimpleDependency.DRUID.getName(),SimpleDependency.DRUID.getCode());
			}
			if(springBootProjectConfig.isTableDocCreated()){
				templatesMap.put(Constants.TABLE_DOC, Constants.TEMPLATE_TABLE_DOC);
			}
			// mybatisplus
			if(springBootProjectConfig.getDependencyMap()!=null && 
					springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.MYBATIS_PLUS.getName())){
				templatesMap.put(Constants.MY_BATIS_PLUS_CONFIG, Constants.TEMPLATE_MY_BATIS_PLUS_CONFIG);
			}
		}
		// logbak
		if(springBootProjectConfig.isOpenLogback()){
			templatesMap.put(Constants.LOGBACK_SPRING, Constants.TEMPLATE_LOGBACK_SPRING);
		}	
		if(springBootProjectConfig.getDependencyMap()!=null){
			// redis
			if(springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.REDIS.getName())){
				templatesMap.put(Constants.REDIS_CONFIG, Constants.TEMPLATE_REDIS_CONFIG);
				templatesMap.put(Constants.REDIS_SERVICE, Constants.TEMPLATE_REDIS_SERVICE);
				templatesMap.put(Constants.REDIS_SERVICE_IMPL, Constants.TEMPLATE_REDIS_SERVICE_IMPL);
			}
			// mongoDB
			if(springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.MONGODB.getName())){
				templatesMap.put(Constants.MONGODB_PAGE, Constants.TEMPLATE_MONGODB_PAGE);
				templatesMap.put(Constants.MONGODB_SERVICE, Constants.TEMPLATE_MONGODB_SERVICE);
				templatesMap.put(Constants.MONGODB_SERVICE_IMPL, Constants.TEMPLATE_MONGODB_SERVICE_IMPL);
				templatesMap.put(Constants.MONGODB_REFLECTIONUTILS, Constants.TEMPLATE_MONGODB_REFLECTIONUTILS);
			}
			// mail
			if(springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.MAIL.getName())){
				templatesMap.put(Constants.MAIL, Constants.TEMPLATE_MAIL);
				templatesMap.put(Constants.MAIL_SERVICE, Constants.TEMPLATE_MAIL_SERVICE);
				templatesMap.put(Constants.MAIL_SERVICE_IMPL, Constants.TEMPLATE_MAIL_SERVICE_IMPL);
				if(!springBootProjectConfig.isOpenView()){
					templatesMap.put(Constants.TEMPLATES, Constants.TEMPLATES);
					templatesMap.put(Constants.STATIC, Constants.STATIC);
				}else{
					if(springBootProjectConfig.getViewType().equals(WebViewType.JSP.getName())){
						templatesMap.put(Constants.TEMPLATES, Constants.TEMPLATES);
					}
				}
			}
			// shiro
			if(springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.SHIRO.getName())){
				templatesMap.put(Constants.SHIRO_CONFIG, Constants.TEMPLATE_SHIRO_CONFIG);
				templatesMap.put(Constants.SHIRO_REALM, Constants.TEMPLATE_SHIRO_REALM);
				templatesMap.put(Constants.SHIRO_UTILS, Constants.TEMPLATE_SHIRO_UTILS);
				if(!springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.REDIS.getName())){
					templatesMap.put(Constants.EHCACHE_SHIRO, Constants.TEMPLATE_EHCACHE_SHIRO);
				}
				if(springBootProjectConfig.isOpenView() && springBootProjectConfig.getViewType().equals(WebViewType.FREEMARKER.getName())){
					templatesMap.put(Constants.SHIRO_TAG_FREEMARKER_CONFIG, Constants.TEMPLATE_SHIRO_TAG_FREEMARKER_CONFIG);
				}
			}
			// schedule
			if(springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.SCHEDULE.getName())){
				templatesMap.put(Constants.SCHEDULE_CONFIG, Constants.TEMPLATE_SCHEDULE_CONFIG);
				templatesMap.put(Constants.SCHEDULE_DYNAMIC_TASK, Constants.TEMPLATE_SCHEDULE_DYNAMIC_TASK);
			}
			// quartz
			if(springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.QUARTZ.getName())){
				if(Objects.equals(springBootProjectConfig.getSpringBootVersion().substring(0,1), "1")){
					templatesMap.put(Constants.QUARTZ, Constants.TEMPLATE_QUARTZ);
					templatesMap.put(Constants.QUARTZ_CONFIG, Constants.TEMPLATE_QUARTZ_CONFIG);
				}
				templatesMap.put(Constants.QUARTZ_SERVICE, Constants.TEMPLATE_QUARTZ_SERVICE);
				templatesMap.put(Constants.QUARTZ_SERVICE_IMPL, Constants.TEMPLATE_QUARTZ_SERVICE_IMPL);
				templatesMap.put(Constants.QUARTZ_TASKINFO, Constants.TEMPLATE_QUARTZ_TASKINFO);
				templatesMap.put(Constants.QUARTZ_TASKJOB, Constants.TEMPLATE_QUARTZ_TASKJOB);
				if(springBootProjectConfig.isOpenDataSource()){
					if(Objects.equals(dataSourceConfig.getType(),DbDriverName.ORACLE.getDb())){

						templatesMap.put(Constants.QUARTZ_TABLES_ORACLE, Constants.TEMPLATE_QUARTZ_TABLES_ORACLE);
					}
					if(Objects.equals(dataSourceConfig.getType(),DbDriverName.MYSQL.getDb())){
						templatesMap.put(Constants.QUARTZ_TABLES_MYSQL, Constants.TEMPLATE_QUARTZ_TABLES_MYSQL);
					}
					if(Objects.equals(dataSourceConfig.getType(),DbDriverName.SQLSERVER.getDb())){
						templatesMap.put(Constants.QUARTZ_TABLES_SQL_SERVER, Constants.TEMPLATE_QUARTZ_TABLES_SQL_SERVER);
					}
				}else{
					templatesMap.put(Constants.QUARTZ_TABLES_ORACLE, Constants.TEMPLATE_QUARTZ_TABLES_ORACLE);
					templatesMap.put(Constants.QUARTZ_TABLES_MYSQL, Constants.TEMPLATE_QUARTZ_TABLES_MYSQL);
					templatesMap.put(Constants.QUARTZ_TABLES_SQL_SERVER, Constants.TEMPLATE_QUARTZ_TABLES_SQL_SERVER);
				}
			}
			// activemq
			if(springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.ACTIVEMQ.getName())){
				templatesMap.put(Constants.ACTIVEMQ_CONFIG, Constants.TEMPLATE_ACTIVEMQ_CONFIG);
				templatesMap.put(Constants.ACTIVEMQ_PRODUCER, Constants.TEMPLATE_ACTIVEMQ_PRODUCER);
				templatesMap.put(Constants.ACTIVEMQ_CONSUMER, Constants.TEMPLATE_ACTIVEMQ_CONSUMER);

			}
			// kafka
			if(springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.KAFKA.getName())){
				templatesMap.put(Constants.KAFKA_PRODUCER, Constants.TEMPLATE_KAFKA_PRODUCER);
				templatesMap.put(Constants.KAFKA_CONSUMER, Constants.TEMPLATE_KAFKA_CONSUMER);
			}
			// rabbitmq
			if(springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.RABBITMQ.getName())){
				templatesMap.put(Constants.RABBITMQ_CONFIG, Constants.TEMPLATE_RABBITMQ_CONFIG);
				templatesMap.put(Constants.RABBITMQ_DIRECT_PRODUCER, Constants.TEMPLATE_RABBITMQ_DIRECT_PRODUCER);
				templatesMap.put(Constants.RABBITMQ_DIRECT_CONSUMER, Constants.TEMPLATE_RABBITMQ_DIRECT_CONSUMER);
				templatesMap.put(Constants.RABBITMQ_FANOUT_PRODUCER, Constants.TEMPLATE_RABBITMQ_FANOUT_PRODUCER);
				templatesMap.put(Constants.RABBITMQ_FANOUT_CONSUMER_1, Constants.TEMPLATE_RABBITMQ_FANOUT_CONSUMER_1);
				templatesMap.put(Constants.RABBITMQ_FANOUT_CONSUMER_2, Constants.TEMPLATE_RABBITMQ_FANOUT_CONSUMER_2);
				templatesMap.put(Constants.RABBITMQ_TOPIC_PRODUCER, Constants.TEMPLATE_RABBITMQ_TOPIC_PRODUCER);
				templatesMap.put(Constants.RABBITMQ_TOPIC_CONSUMER, Constants.TEMPLATE_RABBITMQ_TOPIC_CONSUMER);
				templatesMap.put(Constants.RABBITMQ_TOPIC_CONSUMERS, Constants.TEMPLATE_RABBITMQ_TOPIC_CONSUMERS);
			}
		}
		templateConfig.setTemplatesMap(templatesMap);
		return templateConfig;
	}

	/**
	 * 执行
	 * @throws IOException
	 */
	public void excute() throws IOException{
		logger.debug("---------->> 开始生成项目... <<----------");
		TemplateConfig templateConfig=initTemplateConfig();			
		Map<String, String> templatesMap=templateConfig.getTemplatesMap();
		for (Map.Entry<String, String> entry : templatesMap.entrySet()) {
			//String fileName=entry.getKey();
			String templateName=entry.getValue();			
			String outFile=templateConfig.getOutFile(mavenConfig,templateName);
			if(outFile==null || "".equals(outFile)){
				continue;
			}
			File file = new File(outDir,outFile);
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			if(!templateName.contains(".")){
				if(!file.exists()){
					file.mkdirs();									
				}
			}else{
				if (!file.exists()) {
					file.createNewFile(); 
				}
				Template template=templateConfig.getTemplate(templateName);
				FileOutputStream fos = new FileOutputStream(file); 
				BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, Constants.UTF8)); 
				template.merge(templateConfig.getVelocityContext(), writer); 
				writer.close(); 
				fos.close();
			}	
			logger.debug("---------->> 成功生成项目文件：{}",(outDir + outFile));
		}
		// 生成 quartz tables
		if(springBootProjectConfig.isOpenDataSource()){			
			Connection conn=null;
			try {
				try {
					conn = JDBCUtils.getConnection(
							dataSourceConfig.getDriverClassName(), dataSourceConfig.getUrl(),
							dataSourceConfig.getUsername(), dataSourceConfig.getPassword());
				} catch (SQLException e) {
					throw new GenerateErrorException(e.getMessage());
				}
			} catch (ClassNotFoundException e) {
				throw new GenerateErrorException(e.getMessage());
			}
			if(conn==null){
				throw new GenerateErrorException("invalid data source!");
			}else{
				if(springBootProjectConfig.getDependencyMap()!=null && springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.QUARTZ.getName())){
					String defaultDbType=Constants.TEMPLATE_QUARTZ_TABLES_ORACLE;
					if(templateConfig.getTemplatesMap().containsKey(Constants.QUARTZ_TABLES_MYSQL)){
						defaultDbType=Constants.TEMPLATE_QUARTZ_TABLES_MYSQL;
					}else if(templateConfig.getTemplatesMap().containsKey(Constants.QUARTZ_TABLES_SQL_SERVER)){
						defaultDbType=Constants.TEMPLATE_QUARTZ_TABLES_SQL_SERVER;
					}
					String sqlFile=defaultDbType.substring(1)+Constants.VM_SUFFIX;
					try {
						SqlFileExecutor.execute(conn, sqlFile);
					} catch (Exception e) {						
						logger.error("execute quartz table fail:{}",e.getMessage());
					}
				}
				JDBCUtils.closeConnection(conn);
			}
			// 生成 mybatis-plus
			if(springBootProjectConfig.getDependencyMap()!=null && 
					springBootProjectConfig.getDependencyMap().containsKey(SimpleDependency.MYBATIS_PLUS.getName())){
				logger.debug("---------->> mybatis-plus代码生成器启动 ... <<----------");				
				mybatisPlusConfig.execute();					
			}
		}
		logger.debug("---------->> 所有项目生成完成！！！<<----------");
	}
}
